package com.pince.lifcycleliveav.pushplayer

import android.content.Context
import android.graphics.Bitmap
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import android.view.Gravity
import android.view.ViewGroup
import android.widget.FrameLayout
import com.pince.lifcycleliveav.em.CameraType
import com.pince.lifcycleliveav.em.PushType
import com.pince.lifcycleliveav.em.*
import com.pince.lifcycleliveav.em.VideoQualityType
import com.tencent.rtmp.ITXLivePushListener
import com.tencent.rtmp.TXLivePushConfig
import com.tencent.rtmp.TXLivePusher
import com.tencent.rtmp.TXLivePusher.RGB_RGBA
import com.tencent.rtmp.TXLiveConstants.PAUSE_FLAG_PAUSE_AUDIO
import com.tencent.rtmp.TXLiveConstants.PAUSE_FLAG_PAUSE_VIDEO
import com.tencent.rtmp.ui.TXCloudVideoView
import java.lang.Exception
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10


open class TXPushPlayerExt : FrameLayout, IPushPlayer, GLSurfaceView.Renderer {
    var videoView: GLSurfaceView
    var mLivePushConfig: TXLivePushConfig
    var mLivePusher: TXLivePusher
    var mVideoEncodeGop: Int = 3 //设置关键帧
    var mConnectRetryCount: Int = 5//设置重连次数
    var mVideoFPS: Int = 15//设置视频帧率
    var hardwareAcceleration: Int = ENCODE_VIDEO_AUTO
    var customModeType: Int = CUSTOM_MODE_VIDEO_CAPTURE
    var pauseFlag: Int = PAUSE_FLAG_PAUSE_VIDEO or PAUSE_FLAG_PAUSE_AUDIO
    var mVideoResolution: Int = -1
    private var mCameraType: CameraType = CameraType.FrontCamera

    /**
     * 控制器
     */
    private val mControllers = ArrayList<IPushPlayerController>()
    private val params2: LayoutParams = LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT,
            Gravity.CENTER)

    /**
     * 后台推流默认背景图
     */
    var bitmap: Bitmap? = null

    /**
     * 是否是pk 默认是false
     */
    var pushType = PushType.NONM

    /**
     * 是否设置进入隐私模式，设置垫盘推流
     */
    var isPullBackGroud = true

    var pausePushBitmapTime = 300

    /**
     * 开启推流状态
     */
    var isStartPUSH = false

    /**
     * 是否腾讯预览且推流， 如果开启自定推流预览则需要自己去实现相机预览
     * 或者由三方提供预览
     */
    var isTxPerView = true

    private var mTXCloudVideoView: TXCloudVideoView? = null

    /**
     * 1.初始化一个默认 GLSurfaceView添加到FrameLayout
     * 2.创建推流器，
     * 3.窗前推流器配置
     * 4.设置监听，并通过控制器管理
     */
    init {
        videoView = GLSurfaceView(context)
//        videoView.setRenderer(this)//设置默认Renderer
        this.addView(videoView, params2)
        mLivePusher = TXLivePusher(context)
        mLivePushConfig = TXLivePushConfig()
        mLivePusher.setPushListener(object : ITXLivePushListener {
            override fun onNetStatus(bundle: Bundle) {
                mControllers.forEach {
                    it.onNetStatus(bundle)
                }
            }

            override fun onPushEvent(event: Int, bundle: Bundle?) {
                mControllers.forEach {
                    it.onPlayEvent(event, bundle)
                }
            }

        })
    }

    /**
     * 设置推流器配置参数
     * 1.bitmap设置垫盘，可以选择不使用
     * 2.@param setPauseFlag 设置后台推流的选项。
     * 3.@param setCustomModeType 自定义采集和自定义处理开关。。开启自定义视频采集CUSTOM_MODE_VIDEO_CAPTURE
     * 4.@param setHardwareAcceleration 设置硬件加速选项。。默认值：TXLiveConstants#ENCODE_VIDEO_AUTO，自动选择是否启用硬件加速。
     * 4.@param setVideoFPS 设置视频帧率。。
     * 5.@param setVideoEncodeGop 设置视频编码 GOP。默认值：3，单位为秒。
     * 6.@param setConnectRetryCount 设置重连次数
     * 根据状态是否设置推流模式
     *
     *
     */
    override fun setLivePushConfig(pushType: PushType) {
        setLivePushConfig(pushType, -1)
    }


    override fun setLivePushConfig(pushType: PushType, videoResolution: Int) {
        // bitmap: 用于指定垫片图片，最大尺寸不能超过 1920*1920
        // time：垫片最长持续时间，单位是秒，300即代表最长持续300秒
        // fps：垫片帧率，最小值为 5fps，最大值为 20fps。
        bitmap?.let {
            mLivePushConfig.setPauseImg(bitmap)
            mLivePushConfig.setPauseImg(pausePushBitmapTime, 10)
        }
        mLivePushConfig.setPauseFlag(pauseFlag)////表示同时暂停视频和音频采集
        mLivePushConfig.setCustomModeType(customModeType)
        mLivePushConfig.setHardwareAcceleration(hardwareAcceleration)
        mLivePushConfig.setVideoFPS(mVideoFPS)//设置帧率
        mLivePushConfig.setConnectRetryCount(mConnectRetryCount)//设置默认推流重连次数
        mLivePushConfig.setVideoEncodeGop(mVideoEncodeGop)//设置关键帧
        mVideoResolution = videoResolution
        when (pushType) {
            PushType.NONM -> { // 秀场直播最流行的分辨率
                mLivePushConfig.setVideoResolution(
                        if (mVideoResolution == -1) VIDEO_RESOLUTION_TYPE_540_960
                        else mVideoResolution
                )
                mLivePushConfig.setAutoAdjustBitrate(true)
                mLivePushConfig.setMinVideoBitrate(400)
                mLivePushConfig.setMaxVideoBitrate(800)
                mLivePushConfig.enableAEC(false)//回声消除
            }
            PushType.PK -> {//pk设置模式
                mLivePushConfig.setVideoResolution(
                        if (mVideoResolution == -1) VIDEO_RESOLUTION_TYPE_480_640
                        else mVideoResolution
                )
                mLivePushConfig.setAutoAdjustBitrate(false)
                mLivePushConfig.setVideoBitrate(800)
                mLivePushConfig.enableAEC(true)
            }
            PushType.LINKVIDEO -> {
                mLivePushConfig.setVideoResolution(
                        if (mVideoResolution == -1) VIDEO_RESOLUTION_TYPE_320_480
                        else mVideoResolution) // 秀场直播连麦
                mLivePushConfig.setAutoAdjustBitrate(true)
                mLivePushConfig.setMinVideoBitrate(100)
                mLivePushConfig.setMaxVideoBitrate(300)
                mLivePushConfig.enableAEC(true)
            }
        }
        mLivePusher.config = mLivePushConfig
        mVideoResolution = -1
    }


    /**
     * 自定义视频采集，向 SDK 发送自己采集的 texture 视频数据。
     * @param data 视频纹理 ID。
     * @param w 视频图像的宽度，不能大于 TXLivePushConfig 中的 videoResolution 属性设定的宽度，否则会失败，小于时 SDK 会自动裁剪。
     * @param h 视频图像的高度，不能大于 TXLivePushConfig 中的 videoResolution 属性设定的宽度，否则会失败，小于时 SDK 会自动裁剪。
     * @return
     *          0：发送成功；
     *          1：视频分辨率非法；
     *          3：视频格式非法；
     *          4：视频图像长宽不符合要求，画面比要求的小了；
     *          1000：SDK 内部错误。
     */
    override fun sendCustomVideoTexture(data: Int, w: Int, h: Int): Int {
        return mLivePusher.sendCustomVideoTexture(data, w, h)
    }

    /**
     * 自定义视频采集，向 SDK 发送自己采集的 YUV 视频数据。
     * @param buffer    byte []	视频数据。
     * @param bufferType    int	视频格式 目前仅支持 YUV_420P 、RGB_RGBA 两种数据格式。
     * @param w    int	视频图像的宽度；不能大于 TXLivePushConfig 中的 videoResolution 属性设定的宽度，否则会失败，小于时 SDK 会自动裁剪。
     * @param h    int	视频图像的高度；不能大于 TXLivePushConfig 中的 videoResolution 属性设定的宽度，否则会失败，小于时 SDK 会自动裁剪。
     * @return
     *      0：发送成功；
     *      1：视频分辨率非法；
     *      2：YUV 数据长度与设置的视频分辨率所要求的长度不一致；
     *      3：视频格式非法；
     *      4：视频图像长宽不符合要求，画面比要求的小了；
     *      1000：SDK 内部错误。
     */
    override fun sendCustomVideoData(data: ByteArray, w: Int, h: Int): Int {
        return mLivePusher.sendCustomVideoData(data, RGB_RGBA, w, h)
    }


    /**
     * 推流控制器Controller
     */
    override fun addPushPlayerCtroller(pushPlayerController: IPushPlayerController) {
        mControllers.add(pushPlayerController)
        pushPlayerController.attachPlayer(this)
    }


    /**
     * 开始推流
     */
    override fun startPush(url: String): Int {
        setLivePushConfig(pushType)
        val type = mLivePusher.startPusher(url)
        Log.e("TXPusher", "startPusher")
        isStartPUSH = true
        mTXCloudVideoView?.let {
            if (!isTxPerView) {
                this.removeView(mTXCloudVideoView)
            }
        }
        return type
    }

    /**
     * @param videoQualityType 设置画质模式
     * @param quality 画质类型（标清、高清、超高清）。
     * @param adjustBitrate 动态码率开关 。
     *                      动态码率不支持 连麦，秀场模式
     * @param quality 默认false 即将废弃
     */
    fun setVideoQuality(videoQualityType: VideoQualityType) {
        Log.e("TXPusher", "当前画质setVideoQuality：$videoQualityType")
        when (videoQualityType) {
            VideoQualityType.SD -> { //标清
                mLivePusher.setVideoQuality(VIDEO_QUALITY_STANDARD_DEFINITION, false, false)
            }

            VideoQualityType.HD -> {//高清
                mLivePusher.setVideoQuality(VIDEO_QUALITY_HIGH_DEFINITION, true, false)
            }

            VideoQualityType.FHD -> {//超清
                mLivePusher.setVideoQuality(VIDEO_QUALITY_SUPER_DEFINITION, true, false)
            }

            VideoQualityType.BD -> {//超清
                mLivePusher.setVideoQuality(VIDEO_QUALITY_ULTRA_DEFINITION, true, false)
            }

            VideoQualityType.LINKMACMAIN -> {//连麦大界面
                mLivePusher.setVideoQuality(VIDEO_QUALITY_LINKMIC_MAIN_PUBLISHER, false, false)
            }
            VideoQualityType.LINKMACSUB -> {//连麦小界面
                mLivePusher.setVideoQuality(VIDEO_QUALITY_LINKMIC_SUB_PUBLISHER, false, false)
            }
        }
    }

    /**
     * 设置是否使用GLSurfView来推流
     */
    override fun setGLSurfView(glSurfaceView: GLSurfaceView): GLSurfaceView {
        this.removeAllViews()
        isTxPerView = false
        videoView = glSurfaceView
        this.addView(videoView, params2)
        return videoView
    }

    /**
     * 美颜
     * @param style 磨皮风格：  0：光滑  1：自然  2：朦胧
     * @param beautyLevel 磨皮等级： 取值为 0-9.取值为 0 时代表关闭美颜效果.默认值: 0,即关闭美颜效果.
     * @param whiteningLevel 美白等级： 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果
     * @param ruddyLevel 红润等级： 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.
     */
    override fun setBeautyFilter(style: Int, beautyLevel: Int, whiteningLevel: Int, ruddyLevel: Int): Boolean {
        return mLivePusher.setBeautyFilter(style, beautyLevel, whiteningLevel, ruddyLevel)
    }

    /**
     * 开始预览预览的时候填充一个腾讯自己的预览界面填充进去，
     * 这里可以选择是否需要开启预览
     * @param isTxPerView true 表示使用腾讯预览
     */
    override fun startPreView(isTxPerView: Boolean) {
        this.isTxPerView = isTxPerView
        if (isTxPerView) {
            //如果腾讯自带预览
            mTXCloudVideoView = TXCloudVideoView(context)
            this.addView(mTXCloudVideoView, params2)
            mLivePusher.startCameraPreview(mTXCloudVideoView)
        }
    }


    /**
     * 设置摄像头前后状态使用前置还是后置
     */
    override fun switchCamera(cameraType: CameraType) {
        mCameraType = cameraType
        mLivePusher.switchCamera()
    }

    /**
     * 根据状态判断使用前后摄像头
     */
    override fun switchCamera() {
        if (mCameraType == CameraType.FrontCamera) {
            switchCamera(CameraType.BackCamera)
        } else {
            switchCamera(CameraType.FrontCamera)
        }
    }

    /**
     * 是否使用镜像
     */
    override fun setMirror(isMirror: Boolean) {
        mLivePusher.setMirror(isMirror)
    }

    /**
     * 停止推流，
     */
    override fun stopRtmpPublish() {
        mLivePusher.setVideoProcessListener(null)
        mLivePusher.setPushListener(null)    //解绑 listener
        mLivePusher.stopPusher()             //停止推流
        mLivePusher.stopCameraPreview(true)  //停止摄像头预览
        this.removeAllViews()
        Log.e("TXPusher", "stopRtmpPublish")
        mControllers.clear()
        bitmap = null
        isStartPUSH = false
    }


    /**
     * 暂停推流
     */
    override fun onActivityPause() {
        try {
            if (isStartPUSH) { //开始推流之后
                if (isPullBackGroud) {
                    Log.e("TXPusher", "pausePusher")
                    mLivePusher.pausePusher() // 通知 SDK 进入“后台推流模式”了
                }
                videoView.onPause()  // mCaptureView 是摄像头的图像渲染view
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 重新开始推流
     */
    override fun onActivityResume() {
        if (isStartPUSH) {  //开始推流之后
            if (isPullBackGroud) {
                Log.e("TXPusher", "resumePusher")
                mLivePusher.resumePusher() // 通知 SDK 重回前台推流
            }
            try {
                videoView.onResume()   // mCaptureView 是摄像头的图像渲染view
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    constructor(context: Context) : super(context)
    constructor(context: Context, mAttributeSet: AttributeSet?) : super(context, mAttributeSet)

    override fun isStartPushing(): Boolean {
        return isStartPUSH
    }

    override fun onDrawFrame(gl: GL10?) {
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height);
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
    }
}